<script setup lang="ts">
import { ref, unref, watch } from 'vue'
import { propTypes } from '@/utils/propTypes'
import { GetItems } from '@/api/base/enumDic'
import { itemBody } from '@/api/types/dictType'
import { joinStr } from '@/utils'

const props = defineProps({
  dicKey: propTypes.string,
  clearable: propTypes.bool.def(true),
  readonly: propTypes.bool.def(false),
  disabled: propTypes.bool.def(false),
  modelValue: propTypes.any,
  placeholder: propTypes.string.def('选择字典'),
  filters: propTypes.array,
  limit: propTypes.array,
  source: propTypes.object,
  labelField: propTypes.string,
  filterFunc: propTypes.func,
  multiple: propTypes.bool.def(false),
  mode: propTypes.string.def('select'),
  sysHead: propTypes.string.def('hr')
})
let sour: itemBody[] = []
const items = ref<itemBody[]>([])
const curVal = ref<any>(null)
const chioses = ref<itemBody[]>([])
const emit = defineEmits(['load', 'change', 'update:modelValue'])

const refreshLabel = () => {
  if (props.source == null || props.labelField == null) {
    return
  } else if (props.readonly) {
    unref(props.source)[props.labelField] = joinStr(unref(chioses), (c: itemBody) => c.Text)
  } else if (curVal.value == null || curVal.value.length === 0) {
    unref(props.source)[props.labelField] = null
  } else if (Array.isArray(curVal.value)) {
    const list = curVal.value
    const item = items.value.filter((c) => list.includes(c.Value))
    unref(props.source)[props.labelField] = joinStr(item, (c: itemBody) => c.Text)
  } else {
    const item = items.value.find((c) => c.Value == curVal.value)
    unref(props.source)[props.labelField] = item?.Text
  }
}
const chooseChange = (value) => {
  let item
  if (value != null) {
    if (props.multiple) {
      item = items.value.filter((c) => value.includes(c.Value))
    } else {
      item = items.value.find((c) => c.Value === value)
    }
  }
  refreshLabel()
  emit('update:modelValue', value)
  emit('change', value, item)
}
const loadDic = async () => {
  const res = await GetItems(props.dicKey, props.sysHead)
  sour = res
  resetFilter()
  emit('load', res)
  loadNames()
}
const resetFilter = () => {
  if (sour.length == 0) {
    return
  }
  if (props.filterFunc) {
    items.value = props.filterFunc(sour)
  } else if (props.filters) {
    items.value = sour.filter((c) => !props.filters.includes(c.Value))
  } else if (props.limit) {
    items.value = sour.filter((c) => props.limit.includes(c.Value))
  } else {
    items.value = sour
  }
}
const loadNames = () => {
  if (curVal.value == null || props.readonly === false) {
    chioses.value = []
  } else if (props.multiple && curVal.value.length > 0) {
    chioses.value = items.value.filter((c) => curVal.value.includes(c.Value))
  } else if (props.multiple === false) {
    chioses.value = items.value.filter((c) => c.Value === curVal.value)
  } else {
    chioses.value = []
  }
  refreshLabel()
}
watch(
  () => props.dicKey,
  (dic: string) => {
    if (dic) {
      loadDic()
    }
  },
  {
    immediate: true
  }
)
watch(
  () => props.filters,
  (dic: Array<unknown>) => {
    if (dic) {
      resetFilter()
    }
  },
  {
    immediate: false
  }
)
watch(
  () => props.limit,
  (dic: Array<unknown>) => {
    if (dic) {
      resetFilter()
    }
  },
  {
    immediate: false
  }
)

watch(
  () => props.modelValue,
  (val: any) => {
    if (props.multiple) {
      curVal.value = Array.isArray(val) ? val : []
    } else {
      curVal.value = val
    }
    loadNames()
  },
  {
    immediate: true
  }
)
</script>
<template>
  <div v-if="props.readonly" :class="'itemNames ' + $attrs.class">
    <span v-for="item in chioses" :key="item.Value">{{ item.Text }}</span>
  </div>
  <el-checkbox-group
    v-else-if="props.mode == 'button' && props.multiple == true && curVal != null"
    v-model="curVal"
    :disabled="props.disabled"
    :style="$attrs.style"
    :class="$attrs.class"
    @change="chooseChange"
  >
    <el-checkbox-button v-for="item in items" :key="item.Value" :label="item.Value">{{
      item.Text
    }}</el-checkbox-button>
  </el-checkbox-group>
  <el-select
    v-else-if="props.mode == 'select'"
    v-model="curVal"
    :disabled="props.disabled"
    :placeholder="props.placeholder"
    :style="$attrs.style"
    :clearable="props.clearable"
    :class="$attrs.class ?? 'el-input'"
    :multiple="props.multiple"
    @change="chooseChange"
  >
    <el-option v-for="item in items" :key="item.Value" :label="item.Text" :value="item.Value" />
  </el-select>
  <el-radio-group
    v-else-if="props.mode == 'radio' && props.multiple == false"
    v-model="curVal"
    :disabled="props.disabled"
    :class="$attrs.class"
    :style="$attrs.style"
    @input="chooseChange"
  >
    <el-radio v-for="item in items" :key="item.Value" :label="item.Value">{{ item.Text }}</el-radio>
  </el-radio-group>
  <el-radio-group
    v-else-if="props.mode == 'button' && props.multiple == false"
    v-model="curVal"
    :disabled="props.disabled"
    :class="$attrs.class"
    @input="chooseChange"
  >
    <el-radio-button v-for="item in items" :key="item.Value" :label="item.Value">{{
      item.Text
    }}</el-radio-button>
  </el-radio-group>
</template>

<style lang="less" scoped>
.itemNames {
  display: inline-block;
  line-height: 20px;
}
.itemNames .el-tag {
  margin-right: 5px;
}
</style>
